
package com.ideacome.test.common.mock.config.annotation;

import java.util.Collection;

import com.ideacome.test.common.mock.interceptor.MockingConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.CollectionUtils;

/**
 * 抽象mock配置类  读取enableMocking注解
 *
 * @author 罗成
 */
@Configuration
public abstract class AbstractMockingConfiguration implements ImportAware {

    protected AnnotationAttributes enableMocking;

    protected boolean needMock;

    protected String keyPrefix;

    protected CacheManager cacheManager;

    protected CacheResolver cacheResolver;

    protected KeyGenerator keyGenerator;

    protected CacheErrorHandler errorHandler;


    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        this.enableMocking = AnnotationAttributes.fromMap(
                importMetadata.getAnnotationAttributes(EnableMocking.class.getName(), false));
        if (this.enableMocking == null) {
            throw new IllegalArgumentException(
                    "@EnableMocking is not present on importing class " + importMetadata.getClassName());
        }
    }

    @Autowired(required = false)
    void setConfigurers(Collection<MockingConfigurer> configurers) {
        if (CollectionUtils.isEmpty(configurers)) {
            return;
        }
        if (configurers.size() > 1) {
            throw new IllegalStateException(configurers.size() + " implementations of " +
                    "CachingConfigurer were found when only 1 was expected. " +
                    "Refactor the configuration such that CachingConfigurer is " +
                    "implemented only once or not at all.");
        }
        MockingConfigurer configurer = configurers.iterator().next();
        useCachingConfigurer(configurer);
    }

    /**
     * Extract the configuration from the nominated {@link MockingConfigurer}.
     */
    protected void useCachingConfigurer(MockingConfigurer config) {
        this.cacheManager = config.cacheManager();
        this.cacheResolver = config.cacheResolver();
        this.keyGenerator = config.keyGenerator();
        this.errorHandler = config.errorHandler();
        this.needMock = config.needMock();
        this.keyPrefix = config.keyPrefix();
    }

}
